"use client";
import dynamic from 'next/dynamic';
import React, { useCallback, useMemo, useState } from 'react';
import {
  Button,
  Card,
  Col,
  DatePicker,
  Input,
  Row,
  Select,
  Space,
  Table,
  Typography,
  message,
  Modal,
  Empty,
} from 'antd';
import { Popover } from 'antd';
import type { ColumnsType } from 'antd/es/table';
import dayjs, { Dayjs } from 'dayjs';
import { CategoryStat, getStats, getTopExamples, buildTaxonomy, runClassify, getVersions } from '../../lib/api';
import RunDrawer from '../../components/RunDrawer';
import CategoriesDrawer from '../../components/CategoriesDrawer';

const ReactECharts = dynamic(() => import('echarts-for-react'), { ssr: false });

const { RangePicker } = DatePicker;
const { Text } = Typography;

const AnalysisPage = () => {
  const [taskVersion, setTaskVersion] = useState<number | undefined>(undefined);
  const [dateRange, setDateRange] = useState<[Dayjs, Dayjs] | null>(null);
  const [search, setSearch] = useState<string>('');
  const [stats, setStats] = useState<CategoryStat[]>([]);
  const [loading, setLoading] = useState<boolean>(false);
  const [selectedCode, setSelectedCode] = useState<string | undefined>(undefined);
  const [refreshTick, setRefreshTick] = useState<number>(0);
  const [runOpen, setRunOpen] = useState<boolean>(false);
  const [seedTaskId, setSeedTaskId] = useState<number | undefined>(undefined);
  const [catsOpen, setCatsOpen] = useState<boolean>(false);
  const [examples, setExamples] = useState<Record<string, string[]>>({});
  const [versions, setVersions] = useState<number[]>([]);
  const timersRef = React.useRef<Record<string, any>>({});
  const [loadingCode, setLoadingCode] = useState<string | null>(null);
  const [isDark, setIsDark] = useState<boolean>(false);

  React.useEffect(() => {
    const update = () => setIsDark(document.documentElement.classList.contains('dark'));
    update();
    const onStorage = (e: StorageEvent) => {
      if (e.key === 'theme') update();
    };
    window.addEventListener('storage', onStorage);
    return () => window.removeEventListener('storage', onStorage);
  }, []);

  const fetchStats = useCallback(async () => {
    setLoading(true);
    try {
      const params: any = {};
      if (taskVersion != null) params.taskVersion = taskVersion;
      if (dateRange) {
        params.dateFrom = dateRange[0].toISOString();
        params.dateTo = dateRange[1].toISOString();
      }
      const data = await getStats(params);
      setStats(data);
    } catch (e: any) {
      message.error(e?.message || '加载统计数据失败');
    } finally {
      setLoading(false);
    }
  }, [taskVersion, dateRange]);

  React.useEffect(() => {
    fetchStats();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [fetchStats, refreshTick]);

  React.useEffect(() => {
    (async () => {
      try {
        const vs = await getVersions();
        setVersions(vs || []);
      } catch {}
    })();
  }, []);

  const onBuildClick = React.useCallback(async () => {
    try {
      await new Promise<void>((resolve, reject) => {
        let pwd = '';
        Modal.confirm({
          title: '请先输入密码',
          content: (
            <div>
              <p>该操作会调用大模型，请确认。</p>
              <Input.Password autoFocus placeholder="请输入密码" onChange={(e) => (pwd = e.target.value)} />
            </div>
          ),
          okText: '确认',
          cancelText: '取消',
          onOk: () => {
            if (pwd === '123456') return Promise.resolve().then(() => resolve());
            message.error('密码不正确');
            return Promise.reject();
          },
          onCancel: () => reject(new Error('CANCELLED')),
        });
      });
      await buildTaxonomy(200);
      message.success('归纳完成');
      setRefreshTick((x) => x + 1);
    } catch (e: any) {
      message.error(e?.message || '归纳失败');
    }
  }, []);

  const onClassifyClick = React.useCallback(async () => {
    try {
      await new Promise<void>((resolve, reject) => {
        let pwd = '';
        Modal.confirm({
          title: '请先输入密码',
          content: (
            <div>
              <p>该操作会调用大模型，请确认。</p>
              <Input.Password autoFocus placeholder="请输入密码" onChange={(e) => (pwd = e.target.value)} />
            </div>
          ),
          okText: '确认',
          cancelText: '取消',
          onOk: () => {
            if (pwd === '123456') return Promise.resolve().then(() => resolve());
            message.error('密码不正确');
            return Promise.reject();
          },
          onCancel: () => reject(new Error('CANCELLED')),
        });
      });
      const res = await runClassify({});
      setSeedTaskId(res.taskId);
      setRunOpen(true);
      message.success(`分类已启动（taskId=${res.taskId}, v=${res.version}）`);
    } catch (e: any) {
      message.error(e?.message || '启动分类失败');
    }
  }, []);

  const onOneClick = React.useCallback(async () => {
    const key = 'oneclick';
    try {
      await new Promise<void>((resolve, reject) => {
        let pwd = '';
        Modal.confirm({
          title: '请先输入密码',
          content: (
            <div>
              <p>该操作会调用大模型，请确认。</p>
              <Input.Password autoFocus placeholder="请输入密码" onChange={(e) => (pwd = e.target.value)} />
            </div>
          ),
          okText: '确认',
          cancelText: '取消',
          onOk: () => {
            if (pwd === '123456') return Promise.resolve().then(() => resolve());
            message.error('密码不正确');
            return Promise.reject();
          },
          onCancel: () => reject(new Error('CANCELLED')),
        });
      });
      message.loading({ content: '正在归纳类目...', key, duration: 0 });
      await buildTaxonomy(200);
      message.loading({ content: '正在启动分类...', key, duration: 0 });
      const res = await runClassify({});
      setSeedTaskId(res.taskId);
      setRunOpen(true);
      message.success({ content: `已启动（taskId=${res.taskId}, v=${res.version}）`, key });
    } catch (e: any) {
      message.error({ content: e?.message || '一键归纳+分类失败', key });
    }
  }, []);

  const filtered = useMemo(() => {
    const q = (search || '').trim().toLowerCase();
    if (!q) return stats;
    return stats.filter(
      (s) => s.code.toLowerCase().includes(q) || s.name.toLowerCase().includes(q),
    );
  }, [stats, search]);

  const pieData = useMemo(
    () =>
      filtered.map((x) => ({
        name: `${x.name} (${x.count}, ${(x.ratio * 100).toFixed(1)}%)`,
        value: x.count,
        code: x.code,
        selected: selectedCode ? x.code === selectedCode : false,
      })),
    [filtered, selectedCode],
  );

  const chartOption = useMemo(
    () => ({
      tooltip: { trigger: 'item', backgroundColor: isDark ? '#333' : '#fff', textStyle: { color: isDark ? '#eee' : '#333' } },
      legend: { type: 'scroll' as const, textStyle: { color: isDark ? '#ddd' : '#333' } },
      series: [
        {
          name: 'Categories',
          type: 'pie' as const,
          radius: ['40%', '70%'],
          avoidLabelOverlap: true,
          itemStyle: { borderRadius: 6, borderColor: '#fff', borderWidth: 1 },
          emphasis: { scale: true },
          label: { show: false },
          labelLine: { show: false },
          data: pieData,
          selectedMode: 'single' as const,
        },
      ],
    }),
    [pieData, isDark],
  );

  const onChartClick = useCallback((params: any) => {
    if (params?.data?.code) setSelectedCode(params.data.code as string);
  }, []);

  const columns: ColumnsType<CategoryStat & { key: string }> = useMemo(
    () => [
      {
        title: 'Code',
        dataIndex: 'code',
        sorter: (a, b) => a.code.localeCompare(b.code),
        width: 160,
      },
      {
        title: 'Name',
        dataIndex: 'name',
        sorter: (a, b) => a.name.localeCompare(b.name),
        render: (_: any, record) => {
          const code = record.code;
          const list = examples[code];
          const content = (
            <div style={{ maxWidth: 360 }}>
              {loadingCode === code && <div style={{ padding: 6 }}>加载中...</div>}
              {!loadingCode && (!list || list.length === 0) && (
                <div style={{ padding: 6, color: '#999' }}>暂无示例</div>
              )}
              {list && list.length > 0 && (
                <ul style={{ padding: 0, margin: 0 }}>
                  {list.map((t, idx) => (
                    <li key={idx} style={{ listStyle: 'disc', marginLeft: 16, marginBottom: 4 }}>{t}</li>
                  ))}
                </ul>
              )}
            </div>
          );
          return (
            <Popover
              title={`代表样本(${code})`}
              content={content}
              mouseEnterDelay={0.1}
              onOpenChange={(visible) => {
                if (!visible) return;
                // debounce 100ms
                if (timersRef.current[code]) {
                  clearTimeout(timersRef.current[code]);
                }
                timersRef.current[code] = setTimeout(async () => {
                  try {
                    setLoadingCode(code);
                    const data = await getTopExamples(code, 3);
                    setExamples((prev) => ({ ...prev, [code]: data.map((d) => d.backDetail) }));
                  } catch (e) {
                    setExamples((prev) => ({ ...prev, [code]: [] }));
                  } finally {
                    setLoadingCode((c) => (c === code ? null : c));
                  }
                }, 100);
              }}
            >
              <span>{record.name}</span>
            </Popover>
          );
        },
      },
      {
        title: 'Count',
        dataIndex: 'count',
        sorter: (a, b) => a.count - b.count,
        width: 120,
      },
      {
        title: 'Ratio',
        dataIndex: 'ratio',
        sorter: (a, b) => a.ratio - b.ratio,
        width: 140,
        render: (v: number) => `${(v * 100).toFixed(2)}%`,
      },
    ],
    [],
  );

  const tableData = useMemo(
    () =>
      filtered.map((s) => ({
        key: s.code,
        ...s,
      })),
    [filtered],
  );

  return (
    <div className="space-y-4">
      <Card>
        <Space wrap>
          <Space size={6}>
            <Text>Task Version:</Text>
            <Select
              style={{ width: 200 }}
              allowClear
              placeholder="Latest (default)"
              value={taskVersion as any}
              onChange={(v) => setTaskVersion(v as number | undefined)}
              options={versions.map((v) => ({ label: `v${v}`, value: v }))}
              showSearch
              optionFilterProp="label"
            />
            <Button size="small" onClick={() => setTaskVersion(undefined)}>使用最新</Button>
          </Space>
          <Space size={6}>
            <Text>时间范围:</Text>
            <RangePicker
              showTime
              value={dateRange as any}
              onChange={(v) => setDateRange((v as any) as [Dayjs, Dayjs] | null)}
              allowClear
            />
          </Space>
          <Input.Search
            placeholder="搜索 code/name"
            allowClear
            onSearch={setSearch}
            onChange={(e) => setSearch(e.target.value)}
            style={{ width: 240 }}
            value={search}
          />
          <Button onClick={onBuildClick}>完成归纳</Button>
          <Button onClick={onClassifyClick}>完成分类</Button>
          <Button type="primary" onClick={onOneClick}>一键归纳+分类</Button>
          <Button onClick={() => setRefreshTick((x) => x + 1)}>刷新</Button>
          <Button type="primary" onClick={() => setRunOpen(true)}>批处理</Button>
          <Button onClick={async () => { try { const Papa = await import("papaparse"); const rows = filtered.map(r => ({ code: r.code, name: r.name, count: r.count, ratio: r.ratio })); const csv = Papa.unparse(rows, { header: true }); const bom = "\uFEFF"; const content = bom + csv; const now = new Date(); const ts = `${now.getFullYear()}${String(now.getMonth()+1).padStart(2,"0")}${String(now.getDate()).padStart(2,"0")}_${String(now.getHours()).padStart(2,"0")}${String(now.getMinutes()).padStart(2,"0")}`; const file = `stats_${taskVersion ?? "latest"}_${ts}.csv`; const blob = new Blob([content], { type: "text/csv;charset=utf-8;" }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = file; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } catch (e) { message.error((e as any)?.message || "导出失败"); } }}>导出 CSV</Button>
          <Button onClick={() => { window.location.href = '/taxonomy/review'; }}>审核不确定分类</Button>
          <Button onClick={() => setCatsOpen(true)}>类目</Button>
        </Space>
      </Card>

      <Row gutter={16}>
        <Col xs={24} lg={12}>
          <Card title="分类占比">
            {pieData.length === 0 ? (
              <div style={{ height: 420, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                <Empty description="暂无数据" />
              </div>
            ) : (
              <ReactECharts
                option={chartOption}
                notMerge
                lazyUpdate
                style={{ height: 420 }}
                onEvents={{ click: onChartClick }}
              />
            )}
          </Card>
        </Col>
        <Col xs={24} lg={12}>
          <Card title="分类列表">
            <Table
              size="middle"
              loading={loading}
              columns={columns}
              dataSource={tableData}
              pagination={{ pageSize: 10, showSizeChanger: true }}
              rowClassName={(record) =>
                record.code === selectedCode ? 'bg-blue-50 dark:bg-blue-900/30' : ''
              }
              onRow={(record) => ({
                onClick: () => setSelectedCode(record.code),
              })}
            />
          </Card>
        </Col>
      </Row>

      <RunDrawer
        open={runOpen}
        onClose={() => setRunOpen(false)}
        initialTaskId={seedTaskId}
        onDone={() => setRefreshTick((x) => x + 1)}
      />
      <CategoriesDrawer open={catsOpen} onClose={() => setCatsOpen(false)} />
    </div>
  );
};

export default AnalysisPage;
